int serial_data = 2;
int shift_clock = 3;
int register_clock = 4;

int i = 0;
int j = 0;
boolean lamps[20][4];
int flash_counter = 0;
int coluna=0;
int bloco=0;

int read_lamps = 0;
int temp=0;

void setup()
{
  Serial.begin(19200);
  pinMode(serial_data, OUTPUT);
  pinMode(shift_clock, OUTPUT);
  pinMode(register_clock, OUTPUT);
  for (i=0;i<20;i++)
  {
    for (j=0;j<4;j++)
    {
      lamps[i][j] = false;
    }
  }
}

void send_bit(int value){
  digitalWrite(serial_data, value);    
  digitalWrite(shift_clock, HIGH);
  digitalWrite(shift_clock, LOW);    
}

void loop()                     // run over and over again
{
  byte val;
  if (Serial.available()){
    val= Serial.read();
    
    if (read_lamps){
      for (i=1,j=0;i<256;i*=2,j++){
        if (j<4)
          lamps[(read_lamps-1)*2][j] = (val & i);
        else
          lamps[(read_lamps-1)*2+1][j-4] = (val & i);
      }
      read_lamps++;
      if (read_lamps > 10) read_lamps = 0;
    } else {
      if (val=='L'){
        read_lamps=1;
      }
    }
  }

//just flash the lamps in predefined patterns
#if 0

  if (flash_counter++ > 500){
    flash_counter = 0;
    temp=(temp+1)%40;

//one lamp at a time

    for (i=0;i<4;i++){
      for (j=0;j<20;j++){
        lamps[j][i] = (temp==80-(20*i+j));
      }
    }
  }

#endif

  coluna = (coluna+1)%4;
  if (coluna==0){
    bloco = (bloco+1)%2;
  }
  int col, linha;
  //send new lamp data to the lamps board through serial interface


//como eu inverti a ordem dos bits,
// o código fica um pouco mais complicado:

//primeiro byte:
//linhas 0 a 7 
  for (linha=0;linha<8;linha++){
    send_bit ((bloco==1) && lamps[7-linha][coluna]);
  }

//segundo byte:
//linhas 12 a 15
  for (linha=0;linha<4;linha++){
    send_bit ((bloco==0) && lamps[15-linha][coluna]);
  }


//linhas 8 a 11
  for (linha=0;linha<4;linha++){
    send_bit ((bloco==1) && lamps[11-linha][coluna]);
  }

//terceiro byte:
//colunas 0 a 3
  for (col=0;col<4;col++){
    send_bit ((3-col) == coluna);
  }

//linhas 16 a 19
  for (linha=0;linha<4;linha++){
    send_bit ((bloco==0) && lamps[19-linha][coluna]);
  }

  //update lamps by sending a clock signal to the registers
  digitalWrite(register_clock, HIGH);
  digitalWrite(register_clock, LOW);
}

